﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  CalendarRulesItemMonitor.cs
//    
// Abstract:
//
//  This module implements the CalendarRulesItemMonitor class. This class monitors for changes to calendar items that potentially 
//  match one of the calendar item rules.
//
//--

using System;
using System.Diagnostics;
using Microsoft.OfficeCommunicationsServer.Applications.Common;

namespace Microsoft.EnhancedReminders.Scheduler
{
    /// <summary>
    /// This class monitors for changes to calendar items that potentially match one of the calendar item rules.
    /// </summary>
    internal class CalendarRulesItemMonitor : Monitor
    {
        // Name of the search folder. A GUID is used to reduce the likelihood that the name is already in use. A constant
        // value is used so that any orphaned folders from the previous instance of the Scheduler service can be deleted 
        // when the service starts.
        private const string _calendarRulesSearchFolderName = "6C8BBD25-7509-4dcd-9F32-580AD2B6F3E7";

        // Notification events of interest to this monitor. For calendar rules items, all events except deletion are of interest.
        private static NotificationEventTypeType[] _events = new NotificationEventTypeType[] {
            NotificationEventTypeType.NewMailEvent,  NotificationEventTypeType.CopiedEvent, NotificationEventTypeType.CreatedEvent,
            NotificationEventTypeType.ModifiedEvent, NotificationEventTypeType.MovedEvent };

        /// <summary>
        /// ctor.
        /// </summary>
        /// <param name="client">WCF proxy for communicating with EWS</param>
        /// <param name="impersonation">Exchange impersonation info</param>
        /// <param name="emailAddress">Mailbox account to be monitored</param>
        /// <param name="taskSerializer">Task serializer</param>
        internal CalendarRulesItemMonitor(ExchangeServicePortType client, ExchangeImpersonationType impersonation, string emailAddress, 
                TaskSerializer taskSerializer)

            : base(client, impersonation, emailAddress, _calendarRulesSearchFolderName, 
                ExchangeHelpers.GetDistinguishedFolder(DistinguishedFolderIdNameType.root, emailAddress), 
                ExchangeHelpers.GetDistinguishedFolder(DistinguishedFolderIdNameType.calendar, emailAddress),
                SearchFolderTraversalType.Shallow, _events, taskSerializer)
        {
        }

        /// <summary>
        /// Handles notifications from EWS about deletions of items matching one of the calendar rules.
        /// </summary>
        /// <param name="context">Logging context</param>
        /// <param name="change">Description of changed item</param>
        /// <param name="previousWatermark">Previous watermark from the previous update</param>
        /// <param name="subscriptionId">Subscription ID associated with this notification</param>
        /// <remarks>
        /// This method is overridden in this class because there should be no deletion notifications from EWS for 
        /// calendar rules items.
        /// </remarks>
        /// <returns>
        /// true if the update is successful; false otherwise
        /// </returns>
        internal override bool OnItemDeleted(ServerContext context, BaseObjectChangedEventType change, string previousWatermark, string subscriptionId)
        {
            Debug.Assert(context != null, "context != null");
            Debug.Assert(change != null, "change != null");
            Debug.Assert(!String.IsNullOrEmpty(subscriptionId), "!String.IsNullOrEmpty(subscriptionId)");

            if (!IsValidUpdate(context, change.Watermark, previousWatermark, subscriptionId))
            {
                // Unexpected or out-of-date notification
                return false;
            }

            // The calendar rules monitor should only get notifications of new and modified items
            Logger.WriteTraceWarning(context, "Unexpected calendar rules deletion notification.");

            return true;
        }

        /// <summary>
        /// Gets the specified item.
        /// </summary>
        /// <param name="taskContext">Task context</param>
        /// <param name="itemId">Storage item to be retrieved</param>
        protected override void GetItem(TaskContext taskContext, ItemIdType itemId)
        {
            Debug.Assert(taskContext != null, "taskContext != null");
            Debug.Assert(itemId != null, "itemId != null");

            GetCalendarItemTask getCalendarItemTask = new GetCalendarItemTask(taskContext, _client, _impersonation, _emailAddress, itemId);
            getCalendarItemTask.Completed += GetItem_Completed;
            _taskSerializer.Execute(getCalendarItemTask);
        }
    }
}
